<template>
  <div class="app-container">
    <!-- 左侧输入区域 -->
    <div class="input-area">
      <div class="left-top">
        <div class="header">
          <h2>前端代码生成器</h2>
        </div>

        <!-- 需求输入 -->
        <div class="requirement-input">
          <div class="input-header">
            <span>输入需求描述</span>
            <div class="button-group">
              <button
                @click="generateCode"
                :disabled="isGenerating || !userRequirement.trim()"
                class="generate-btn">
                {{ isGenerating ? '生成中...' : '生成代码' }}
              </button>
              <button
                v-if="isGenerating"
                @click="cancelGeneration"
                class="cancel-btn">
                取消
              </button>
            </div>
          </div>
          <textarea
            v-model="userRequirement"
            placeholder="请输入您的前端页面需求描述..."
            :disabled="isGenerating"
            class="requirement-textarea">
        </textarea>
        </div>

        <!-- 生成设置 -->
        <div class="generation-settings">
          <div class="settings-header">生成设置</div>

          <!-- 代码类型选择 -->
          <div class="setting-item">
            <div class="setting-label">
              <span>代码类型</span>
              <el-tooltip content="选择生成HTML页面或Vue组件" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
            </div>
            <el-radio-group v-model="codeType" size="small" :disabled="isGenerating">
              <el-radio-button label="html">HTML</el-radio-button>
              <el-radio-button label="vue">Vue组件</el-radio-button>
            </el-radio-group>
          </div>

          <!-- 全局上下文开关 -->
          <div class="setting-item">
            <div class="setting-label">
              <span>使用全局上下文</span>
              <el-tooltip content="开启后，生成过程中会保持对话上下文，组件风格更一致；关闭后，每个组件独立生成，可能更有创意" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
            </div>
            <el-switch v-model="useGlobalContext" :disabled="isGenerating"></el-switch>
          </div>

          <!-- 风格设置模式选择 -->
          <div class="setting-item">
            <div class="setting-label">
              <span>风格设置方式</span>
              <el-tooltip content="选择使用预设选项或自然语言描述来设定页面风格" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
            </div>
            <el-radio-group v-model="styleSettingMode" size="small" :disabled="isGenerating">
              <el-radio-button label="preset">预设选项</el-radio-button>
              <el-radio-button label="description">自然语言描述</el-radio-button>
            </el-radio-group>
          </div>

          <!-- 预设选项风格设置 -->
          <template v-if="styleSettingMode === 'preset'">
            <!-- 页面风格设置 -->
            <div class="setting-item">
              <div class="setting-label">
                <span>页面风格</span>
              </div>
              <el-select v-model="pageStyle.colorScheme" placeholder="颜色方案" :disabled="isGenerating" size="small">
                <el-option label="现代" value="modern"></el-option>
                <el-option label="经典" value="classic"></el-option>
                <el-option label="暗色" value="dark"></el-option>
                <el-option label="亮色" value="light"></el-option>
                <el-option label="多彩" value="colorful"></el-option>
              </el-select>
            </div>

            <div class="setting-item">
              <div class="setting-label">
                <span>布局风格</span>
              </div>
              <el-select v-model="pageStyle.layoutStyle" placeholder="布局风格" :disabled="isGenerating" size="small">
                <el-option label="简洁" value="clean"></el-option>
                <el-option label="密集" value="dense"></el-option>
                <el-option label="极简" value="minimal"></el-option>
                <el-option label="丰富" value="rich"></el-option>
              </el-select>
            </div>

            <div class="setting-item">
              <div class="setting-label">
                <span>UI框架</span>
              </div>
              <el-select v-model="pageStyle.uiFramework" placeholder="UI框架" :disabled="isGenerating" size="small">
                <el-option label="Bootstrap" value="bootstrap"></el-option>
                <el-option label="Tailwind" value="tailwind"></el-option>
                <el-option label="Material" value="material"></el-option>
              </el-select>
            </div>

            <div class="setting-item">
              <div class="setting-label">
                <span>主题色</span>
              </div>
              <div class="color-pickers">
                <el-color-picker v-model="pageStyle.colorVariables['primary-color']" size="small" :disabled="isGenerating"></el-color-picker>
                <el-color-picker v-model="pageStyle.colorVariables['secondary-color']" size="small" :disabled="isGenerating"></el-color-picker>
                <el-color-picker v-model="pageStyle.colorVariables['accent-color']" size="small" :disabled="isGenerating"></el-color-picker>
              </div>
            </div>
          </template>

          <!-- 自然语言风格描述 -->
          <template v-else>
            <div class="setting-item-textarea">
              <div class="setting-label">
                <span>风格描述</span>
                <el-tooltip content="使用自然语言描述您期望的页面风格、配色和布局特点" placement="top">
                  <i class="el-icon-question"></i>
                </el-tooltip>
              </div>
              <el-input
                type="textarea"
                v-model="styleDescription"
                :rows="3"
                placeholder="例如：'我需要一个现代简约风格的界面，以蓝色和白色为主色调，布局简洁清晰，适合数据展示，有点类似于Ant Design的风格'"
                :disabled="isGenerating">
              </el-input>
            </div>
          </template>
        </div>

        <!-- 生成进度 -->
        <div v-if="isGenerating || completedSteps.length > 0" class="generation-progress">
          <div class="progress-header">生成进度</div>
          <div class="unified-progress-list">
            <!-- 基础步骤 -->
            <div
              v-for="(step, idx) in genSteps"
              :key="'step-'+idx"
              class="progress-item"
              :class="{
                'completed': completedSteps.includes(step.toLowerCase().replace(/\s+/g, '_')),
                'current': currentStageMessage.includes(step) && isGenerating
              }">
              <div class="progress-icon">
                <i v-if="completedSteps.includes(step.toLowerCase().replace(/\s+/g, '_'))" class="el-icon-check"></i>
                <i v-else-if="currentStageMessage.includes(step) && isGenerating" class="el-icon-loading"></i>
                <i v-else class="el-icon-more"></i>
              </div>
              <div class="progress-label">{{ step }}</div>
            </div>

            <!-- 区域组件列表 -->
            <template v-if="plannedAreaNames.length > 0">
              <div
                v-for="(areaName, idx) in plannedAreaNames"
                :key="'area-'+idx"
                class="progress-item"
                :class="{
                  'completed': generatedAreaNames.includes(areaName),
                  'current': currentGeneratingComponent === areaName && isGenerating
                }">
                <div class="progress-icon">
                  <i v-if="generatedAreaNames.includes(areaName)" class="el-icon-check"></i>
                  <i v-else-if="currentGeneratingComponent === areaName && isGenerating" class="el-icon-loading"></i>
                  <i v-else class="el-icon-more"></i>
                </div>
                <div class="progress-label">组件: {{ areaName }}</div>
              </div>
            </template>

            <!-- 完成步骤 -->
            <div
              class="progress-item"
              :class="{
                'completed': completedSteps.includes('complete'),
                'current': currentStageMessage.includes('完成') && isGenerating
              }">
              <div class="progress-icon">
                <i v-if="completedSteps.includes('complete')" class="el-icon-check"></i>
                <i v-else-if="currentStageMessage.includes('完成') && isGenerating" class="el-icon-loading"></i>
                <i v-else class="el-icon-more"></i>
              </div>
              <div class="progress-label">完成</div>
            </div>
          </div>
        </div>
      </div>
      <!-- 聊天内容区域 -->
      <div class="chat-content" ref="chatContentRef">
        <div v-if="analysisContent" class="message">
          <div class="message-title">需求分析</div>
          <div class="message-content">
            <pre>{{ analysisContent }}</pre>
          </div>
        </div>

        <div v-if="structureContent" class="message">
          <div class="message-title">页面结构设计</div>
          <div class="message-content">
            <pre>{{ structureContent }}</pre>
          </div>

          <!-- 显示计划生成的区域列表 -->
          <div v-if="plannedAreaNames.length > 0" class="areas-list">
            <div class="areas-title">页面组件列表 ({{ generatedAreaNames.length }}/{{ plannedAreaNames.length }})</div>
            <div class="progress" style="height: 8px; margin-bottom: 10px;">
              <div class="progress-bar" role="progressbar"
                   :style="{width: `${(generatedAreaNames.length / plannedAreaNames.length) * 100}%`}"
                   :aria-valuenow="generatedAreaNames.length"
                   aria-valuemin="0"
                   :aria-valuemax="plannedAreaNames.length"></div>
            </div>
            <div class="area-tags">
              <span v-for="(areaName, idx) in plannedAreaNames"
                    :key="idx"
                    class="area-tag"
                    :class="{
                      'completed': generatedAreaNames.includes(areaName),
                      'current': currentGeneratingComponent === areaName
                    }">
                {{ areaName }}
              </span>
            </div>
          </div>
        </div>

        <div v-if="skeletonCode" class="message">
          <div class="message-title">页面骨架</div>
          <div class="message-content code">
            <pre><code>{{ skeletonCode }}</code></pre>
          </div>
        </div>

        <div v-if="areasCode" class="message">
          <div class="message-title">区域代码</div>
          <div class="message-content code">
            <pre><code>{{ areasCode }}</code></pre>
          </div>

          <!-- 显示已生成的区域 -->
          <div v-if="generatedAreaNames.length > 0" class="areas-progress">
            <div class="areas-title">已生成区域:</div>
            <div class="area-tags">
              <span v-for="(areaName, idx) in generatedAreaNames"
                    :key="idx"
                    class="area-tag completed">
                {{ areaName }}
              </span>
            </div>
          </div>
        </div>
      </div>

    </div>

    <!-- 右侧结果区域 -->
    <div class="result-area">
      <!-- 切换按钮 -->
      <div class="preview-toggle">
        <button
          @click="previewMode = 'rendered'"
          :class="{ active: previewMode === 'rendered' }">
          渲染预览
        </button>
        <button
          @click="previewMode = 'code'"
          :class="{ active: previewMode === 'code' }">
          代码预览
        </button>
      </div>

      <!-- 代码预览 -->
      <div v-if="previewMode === 'code'" class="code-preview">
        <pre><code>{{ generatedCode || areasIntegratedCode || skeletonCode }}</code></pre>
      </div>

      <!-- 渲染预览 -->
      <div v-else class="rendered-preview">
        <!-- HTML预览 -->
        <iframe
          v-if="(codeType === 'html') && (generatedCode || areasIntegratedCode || skeletonCode)"
          ref="previewIframe"
          class="preview-iframe"
          sandbox="allow-scripts allow-same-origin allow-forms allow-downloads"
          allow="autoplay"
          @load="isPreviewLoading = false">
        </iframe>

        <!-- Vue组件预览 -->
        <div v-if="codeType === 'vue'" class="vue-preview-container">
          <RemoteComponent
            ref="remoteComponent"
            v-model:show="showVuePreview"
            :sfc-content="sfcContent || generatedCode || areasIntegratedCode || skeletonCode"
          />
        </div>

        <div v-if="isPreviewLoading" class="preview-loading">
          <div class="spinner"></div>
          <p>加载预览中...</p>
        </div>
        <div v-if="previewError" class="preview-error">
          <i class="el-icon-warning"></i>
          <p>{{ previewError }}</p>
          <button @click="retryPreview" class="retry-btn">重试</button>
        </div>
        <div v-else-if="!generatedCode && !areasIntegratedCode && !skeletonCode" class="empty-preview">
          <p>代码生成后将在此处显示预览</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, nextTick, reactive } from 'vue';
import RemoteComponent from '../component/DynamicComponent.vue';

// 状态变量
const userRequirement = ref('');
const isGenerating = ref(false);
const previewMode = ref<'rendered' | 'code'>('rendered');
const chatContentRef = ref<HTMLElement | null>(null);
const previewIframe = ref<HTMLIFrameElement | null>(null);
const isPreviewLoading = ref(false);
const previewError = ref('');
const remoteComponent = ref<any>(null);
const showVuePreview = ref(false);

// 新增：代码类型选择
const codeType = ref<'html' | 'vue'>('html');

// 新增：全局上下文开关
const useGlobalContext = ref(true);

// 新增: 风格设置模式
const styleSettingMode = ref<'preset' | 'description'>('preset');
// 新增: 自然语言风格描述
const styleDescription = ref('');

// 新增：页面风格设置
const pageStyle = reactive({
  colorScheme: 'modern',
  layoutStyle: 'clean',
  uiFramework: 'bootstrap',
  fontFamily: "'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
  description: "现代简约风格，注重用户体验和视觉层次",
  colorVariables: {
    'primary-color': '#3498db',
    'secondary-color': '#2ecc71',
    'accent-color': '#e74c3c',
    'text-color': '#333333',
    'light-bg': '#f8f9fa',
    'dark-bg': '#343a40'
  }
});

// 生成内容
const analysisContent = ref('');
const structureContent = ref(''); // 页面结构设计内容
const skeletonCode = ref('');
const areasCode = ref(''); // 区域代码内容
const generatedCode = ref('');
// 存储区域整合到骨架后的代码
const areasIntegratedCode = ref('');
// 存储已生成的区域名称
const generatedAreaNames = ref<string[]>([]);
// 存储计划生成的区域名称（从结构设计中提取）
const plannedAreaNames = ref<string[]>([]);
// 当前正在生成的组件
const currentGeneratingComponent = ref<string>('');

// 当前生成阶段
const currentStep = ref(0);
const currentStageMessage = ref('');
const completedSteps = ref<string[]>([]);

// 生成步骤
const steps = ref([
  { id: 'style', label: '风格设定' },
  { id: 'analysis', label: '需求分析' },
  { id: 'skeleton', label: '基础骨架' },
  { id: 'components', label: '组件生成' },
  { id: 'complete', label: '完成集成' }
]);

const genSteps = ref<string[]>([]);

const activeStep = ref(0);
// 请求控制器
let controller: AbortController | null = null;

// 示例需求
const setExampleRequirement = (exampleId: number) => {
  if (exampleId === 1) {
    userRequirement.value = '创建一个Todo列表应用，包含添加、删除、标记完成功能。使用HTML和CSS实现，界面简洁美观。';
  } else if (exampleId === 2) {
    userRequirement.value = '设计一个类似B站的首页，包含导航栏、视频卡片列表和侧边栏。使用Bootstrap实现响应式布局。';
  }
};

// 添加防抖函数，避免频繁更新预览
const debounce = (fn: Function, delay: number) => {
  let timer: number | null = null;
  return (...args: any[]) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn(...args);
      timer = null;
    }, delay) as unknown as number;
  };
};

// 使用防抖处理的预览更新函数
const updatePreview = debounce((code) => {
  renderCodeInIframe(code);
}, 500);

// 实际更新预览的内部函数
const _updatePreview = (code: string) => {
  if (codeType.value === 'html') {
    renderCodeInIframe(code);
  } else {
    updateVuePreview(code);
  }
};

// 重试预览
const retryPreview = () => {
  previewError.value = '';
  // 优先使用最新可用的代码
  const codeToUse = generatedCode.value || areasIntegratedCode.value || skeletonCode.value;

  if (codeToUse) {
    if (codeType.value === 'html') {
      renderCodeInIframe(codeToUse);
    } else {
      updateVuePreview(codeToUse);
    }
  }
};

// 生成代码
const generateCode = async () => {
  if (!userRequirement.value.trim() || isGenerating.value) return;

  // 重置状态
  isGenerating.value = true;
  analysisContent.value = '';
  structureContent.value = '';
  skeletonCode.value = '';
  areasCode.value = '';
  generatedCode.value = '';
  areasIntegratedCode.value = '';
  generatedAreaNames.value = [];
  plannedAreaNames.value = [];
  currentGeneratingComponent.value = '';
  currentStep.value = 0;
  currentStageMessage.value = '准备中...';
  completedSteps.value = [];
  // Vue预览重置
  showVuePreview.value = false;

  // 创建控制器
  controller = new AbortController();
  const { signal } = controller;

  function extracted(dataLine) {
    try {
      // 移除前缀"data:"并清理空白
      const cleanedData = dataLine.replace(/^data:\s*/, '').trim();

      if (cleanedData && cleanedData !== '[DONE]') {
        try {
          const data = JSON.parse(cleanedData);
          processStreamData(data);
        } catch (parseError) {
          console.error('JSON解析错误:', parseError, '原始数据:', cleanedData);


          // 尝试修复可能的JSON格式问题
          try {
            // 检查是否包含多个JSON对象（通常由换行符分隔）
            const jsonParts = cleanedData.split(/\n+/).filter(part => part.trim());
            if (jsonParts.length > 1) {
              console.log('检测到多个JSON对象，尝试分别解析');
              jsonParts.forEach(part => {
                try {
                  const partData = JSON.parse(part);
                  console.log('成功解析部分JSON:', partData);
                  processStreamData(partData);
                } catch (e) {
                  console.error('部分JSON解析失败:', e, '部分数据:', part);
                }
              });
            }
          } catch (recoveryError) {
            console.error('尝试恢复解析失败:', recoveryError);
          }
        }
      }
    } catch (e) {
      console.error('数据处理错误:', e, '原始数据行:', dataLine);
    }
  }

  try {
    console.log('开始发送代码生成请求，需求:', userRequirement.value);

    // 处理页面风格设置
    let styleConfig;
    if (styleSettingMode.value === 'preset') {
      // 使用预设选项
      styleConfig = {
        colorScheme: pageStyle.colorScheme,
        layoutStyle: pageStyle.layoutStyle,
        uiFramework: pageStyle.uiFramework,
        fontFamily: pageStyle.fontFamily,
        description: pageStyle.description,
        colorVariables: pageStyle.colorVariables
      };
    } else {
      // 使用自然语言描述
      styleConfig = {
        description: styleDescription.value,
        // 保留一些默认值，让后端根据描述生成其他配置
        uiFramework: 'auto',
        colorVariables: {}
      };
    }

    // 准备请求数据，包含全局上下文开关和页面风格设置
    const requestData = {
      requirements: userRequirement.value,
      useGlobalContext: useGlobalContext.value,
      pageStyle: styleConfig,
      codeType: codeType.value // 添加代码类型
    };

    console.log('请求参数:', requestData);

    const response = await fetch('http://localhost:18080/aicode/frontcode/generate', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(requestData),
      signal
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const reader = response.body?.getReader();
    if (!reader) {
      throw new Error('Response body is null');
    }


    const decoder = new TextDecoder('utf-8')
    let buffer = ''



    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, {stream: true})
      const messages = buffer.split(/\n\n(?=data:)/)
      buffer = messages.pop() || ''


      for (const msg of messages) {
        extracted(msg);
      }
    }
  } catch (err) {
    if ((err as Error).name !== 'AbortError') {
      console.error('Error generating code:', err);
      currentStageMessage.value = '生成失败，请重试';
    } else {
      currentStageMessage.value = '已取消生成';
    }
  } finally {
    console.log('代码生成请求结束');
    isGenerating.value = false;
    controller = null;
  }
};

// 处理流数据
const processStreamData = (data: any) => {
  // 处理测试消息（独立处理）
  if (data.test) {
    console.log('收到测试消息:', data.test);
    return;
  }

  // 分支1: 处理开始事件
  if (data.status === 'start') {
    console.log('阶段开始:', data.stage, data.message);
    const stageIndex = steps.value.findIndex(step => step.id === data.stage);
    if (stageIndex !== -1) {
      currentStep.value = stageIndex;
      currentStageMessage.value = data.message || `正在${steps.value[stageIndex].label}...`;
    }
  }

  // 分支2: 处理进度更新
  else if (data.status === 'progress') {
    if (data.content) {
      switch (data.stage) {
        case 'analysis':
          analysisContent.value += data.content;
          currentStageMessage.value = '正在分析需求...';
          break;
        case 'structure':
          structureContent.value += data.content;
          break;
        case 'skeleton':
          skeletonCode.value += data.content;
          currentStageMessage.value = '正在生成页面骨架...';
          if (previewMode.value === 'rendered') {
            if (codeType.value === 'html') {
              renderCodeInIframe(skeletonCode.value);
            } else {
              updateVuePreview(skeletonCode.value);
            }
          }
          break;
        case 'component':
          if (data.sectionId) {
            currentGeneratingComponent.value = data.sectionId;
            const componentsStepIndex = steps.value.findIndex(step => step.id === 'components');
            if (componentsStepIndex !== -1 && currentStep.value !== componentsStepIndex) {
              currentStep.value = componentsStepIndex;
            }

            if (!generatedAreaNames.value.includes(data.sectionId)) {
              generatedAreaNames.value.push(data.sectionId);
              console.log('添加新区域到生成列表:', data.sectionId);
            }

            areasCode.value += data.content;
            currentStageMessage.value = `正在生成组件: ${data.sectionId} (${generatedAreaNames.value.length}/${plannedAreaNames.value.length})`;
          } else {
            areasCode.value += data.content;
          }
          break;
        default:
          console.warn('未知的内容更新阶段:', data.stage);
      }
    }
  }

  // 分支3: 处理完成事件
  else if (data.status === 'complete') {
    // 根据不同的 stage 类型分别处理
    switch (data.stage) {
      // 处理风格设置完成事件
      case 'style_complete':
        console.log('风格设置完成:', data.styleInfo);
        if (data.styleInfo) {
          // 可以在这里显示风格信息或更新UI
          currentStageMessage.value = '页面风格设定完成';
        }
        break;

      // 处理区域更新事件
      case 'area_update':
        console.log('区域更新事件触发:', data.areaName);
        activeStep.value = activeStep.value + 1;

        if (data.areaName && !generatedAreaNames.value.includes(data.areaName)) {
          generatedAreaNames.value.push(data.areaName);

          if (currentGeneratingComponent.value === data.areaName) {
            const nextComponent = plannedAreaNames.value.find(name => !generatedAreaNames.value.includes(name));
            currentGeneratingComponent.value = nextComponent || '';
          }

          if (generatedAreaNames.value.length >= plannedAreaNames.value.length && plannedAreaNames.value.length > 0) {
            const completeStepIndex = steps.value.findIndex(step => step.id === 'complete');
            if (completeStepIndex !== -1) {
              currentStep.value = completeStepIndex;
              currentStageMessage.value = '所有组件生成完成，正在集成...';
            }
          }
        }

        if (data.completeContent) {
          const content = typeof data.completeContent === 'string'
            ? data.completeContent
            : (data.completeContent ? JSON.stringify(data.completeContent) : '');
          console.log('代码更新:', content);
          areasIntegratedCode.value = content;

          if (data.areaName) {
            currentStageMessage.value = `完成组件: ${data.areaName} (${generatedAreaNames.value.length}/${plannedAreaNames.value.length})`;
          }

          // 如果在渲染预览模式，立即更新预览
          if (previewMode.value === 'rendered') {
            if (codeType.value === 'html') {
              renderCodeInIframe(content);
            } else {
              updateVuePreview(content);
            }
          }
        }
        break;

      // 处理分析完成事件
      case 'analysis_complete':
        console.log('分析阶段完成');
        if (data.steps && Array.isArray(data.steps)) {
          genSteps.value = data.steps;
          // 如果steps是数组，更新步骤列表
          if (Array.isArray(steps.value)) {
            steps.value = data.steps.map((step: string) => ({
              id: step.toLowerCase().replace(/\s+/g, '_'),
              label: step
            }));
          }
        }
        break;

      // 处理骨架完成事件
      case 'skeleton_complete':
        console.log('骨架生成完成');
        if (!completedSteps.value.includes('skeleton')) {
          completedSteps.value.push('skeleton');
        }

        currentStageMessage.value = '页面骨架生成完成，准备生成组件...';

        if (data.completeContent) {
          const content = typeof data.completeContent === 'string'
            ? data.completeContent
            : (data.completeContent ? JSON.stringify(data.completeContent) : '');

          skeletonCode.value = content;
          console.log('骨架代码更新:', skeletonCode.value);

          // 如果在渲染预览模式，立即更新预览
          if (previewMode.value === 'rendered') {
            if (codeType.value === 'html') {
              renderCodeInIframe(content);
            } else {
              updateVuePreview(content);
            }
          }
        }
        break;

      // 处理组件完成事件
      case 'components_complete':
        console.log('组件生成完成');
        if (!completedSteps.value.includes('components')) {
          completedSteps.value.push('components');
        }

        currentStageMessage.value = '组件生成完成，正在集成最终代码...';

        if (data.completeContent) {
          const content = typeof data.completeContent === 'string'
            ? data.completeContent
            : (data.completeContent ? JSON.stringify(data.completeContent) : '');

          generatedCode.value = content;
          console.log('最终生成代码更新:', generatedCode.value);

          // 如果在渲染预览模式，立即更新预览
          if (previewMode.value === 'rendered') {
            if (codeType.value === 'html') {
              renderCodeInIframe(content);
            } else {
              updateVuePreview(content);
            }
          }
        }
        break;

      // 处理最终完成事件
      case 'all_complete':
        console.log('代码生成全部完成');
        isGenerating.value = false;
        currentStageMessage.value = '代码生成完成';

        const completeStepIndex = steps.value.findIndex(step => step.id === 'complete');
        if (completeStepIndex !== -1) {
          currentStep.value = completeStepIndex;
          if (!completedSteps.value.includes('complete')) {
            completedSteps.value.push('complete');
          }
        }

        currentGeneratingComponent.value = '';
        break;

      // 处理其他类型的完成事件 (兼容可能的扩展)
      default:
        // 尝试处理带有_complete后缀的事件
        if (data.stage?.endsWith('_complete')) {
          const baseStage = data.stage.replace('_complete', '');
          console.log('其他阶段完成:', baseStage);

          if (baseStage && !completedSteps.value.includes(baseStage)) {
            completedSteps.value.push(baseStage);
          }

          if (data.completeContent) {
            const content = typeof data.completeContent === 'string'
              ? data.completeContent
              : (data.completeContent ? JSON.stringify(data.completeContent) : '');

            switch (baseStage) {
              case 'structure':
                structureContent.value = content || '';
                extractAreasList(structureContent.value);
                break;
              case 'areas':
                generatedCode.value = content;
                if (previewMode.value === 'rendered') {
                  renderCodeInIframe(content);
                }
                break;
            }
          }
        } else {
          console.warn('未处理的完成事件类型:', data.stage);
        }
        break;
    }

    // 自动滚动聊天内容区域到底部
    nextTick(() => {
      if (chatContentRef.value) {
        chatContentRef.value.scrollTop = chatContentRef.value.scrollHeight;
      }
    });
  }

  // 处理错误（放在完成事件分支之外）
  else if (data.error) {
    console.error('Error from server:', data.error);
    currentStageMessage.value = `错误: ${data.error}`;
  } else {
    console.warn('未处理的数据类型:', data);
  }
};

// 提取区域列表
const extractAreasList = (content: string) => {
  const areasList: string[] = [];

  // 尝试两种方法提取区域:

  // 方法1: 从HTML注释中提取SECTION标签
  const sectionRegex = /<!--\s*SECTION:\s*([^>-]+?)(?:-->|>)/g;
  let match;
  while ((match = sectionRegex.exec(content)) !== null) {
    const sectionName = match[1].trim();
    if (sectionName && !areasList.includes(sectionName)) {
      areasList.push(sectionName);
    }
  }

  // 方法2: 匹配"区域列表："后面的内容
  if (areasList.length === 0) {
    const listMatch = content.match(/区域列表：\s*([\s\S]*?)(?=\n\n|$)/);
    if (listMatch && listMatch[1]) {
      // 分割每一行
      const lines = listMatch[1].split('\n');

      // 处理每一行，提取区域名称
      for (const line of lines) {
        // 匹配形如"1. AreaName：描述"的格式
        const areaMatch = line.match(/\d+\.\s+([A-Za-z0-9_\u4e00-\u9fa5]+)[:：]/);
        if (areaMatch && areaMatch[1]) {
          areasList.push(areaMatch[1]);
        }
      }
    }
  }

  console.log("提取的区域列表:", areasList);

  // 更新区域列表
  if (areasList.length > 0) {
    plannedAreaNames.value = areasList;
  }
};

// 取消生成
const cancelGeneration = () => {
  if (controller) {
    controller.abort();
    controller = null;
    isGenerating.value = false;
    currentStageMessage.value = '已取消生成';
  }
};

// 创建当前预览的代码缓存
const currentPreviewCode = ref('');

// 直接在iframe中渲染代码，用于实时预览
const renderCodeInIframe = (code: string) => {
  if (!previewIframe.value || !previewIframe.value.contentDocument) return;

  try {
    isPreviewLoading.value = true;
    previewError.value = '';

    // 验证和清理代码
    if (!code || code.trim() === '') {
      previewError.value = '预览代码为空';
      isPreviewLoading.value = false;
      return;
    }

    // 清理代码中的markdown标记
    let cleanCode = code.replace(/```html|```/g, '');

    // 验证HTML是否完整，检查标签平衡
    const hasOpenHtml = cleanCode.includes('<html') || cleanCode.includes('<!DOCTYPE html');
    const hasCloseHtml = cleanCode.includes('</html>');
    const hasOpenBody = cleanCode.includes('<body');
    const hasCloseBody = cleanCode.includes('</body>');

    // 检测到不完整的HTML结构时在控制台打印原始HTML
    if (!hasOpenHtml || !hasCloseHtml || !hasOpenBody || !hasCloseBody) {
      console.warn('检测到不完整的HTML结构:');
      console.log('----------------------------------------');
      console.log(cleanCode);
      console.log('----------------------------------------');
      console.log(`HTML标签状态: 开始标签=${hasOpenHtml}, 结束标签=${hasCloseHtml}`);
      console.log(`Body标签状态: 开始标签=${hasOpenBody}, 结束标签=${hasCloseBody}`);
    }

    // 确保HTML结构完整
    if (!hasOpenHtml) {
      cleanCode = `<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Preview</title>
  <!-- Font Awesome -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
</head>
<body>
${cleanCode}
</body>
</html>`;
      console.log('已添加完整HTML结构');
    } else {
      // 确保有完整的头部
      if (!cleanCode.includes('<head')) {
        cleanCode = cleanCode.replace('<html>', '<html><head><meta charset="UTF-8"><title>Preview</title></head>');
        console.log('已添加缺失的head标签');
      }

      // 确保有完整的body
      if (!hasOpenBody) {
        cleanCode = cleanCode.replace('</html>', '<body></body></html>');
        // 找到</head>后插入内容
        const headEndIndex = cleanCode.indexOf('</head>');
        if (headEndIndex !== -1) {
          const beforeHead = cleanCode.substring(0, headEndIndex + 7);
          const afterHead = cleanCode.substring(headEndIndex + 7);
          cleanCode = beforeHead + '<body>' + afterHead;
          console.log('已在</head>后添加<body>标签');
        }
      }

      // 确保闭合标签
      if (!hasCloseBody && hasOpenBody) {
        cleanCode = cleanCode + '</body>';
        console.log('已添加缺失的</body>标签');
      }

      if (!hasCloseHtml) {
        cleanCode = cleanCode + '</html>';
        console.log('已添加缺失的</html>标签');
      }
    }

    // 检查HTML结构平衡
    try {
      const parser = new DOMParser();
      const doc = parser.parseFromString(cleanCode, 'text/html');
      // 检查解析错误
      const parseError = doc.querySelector('parsererror');
      if (parseError) {
        console.warn('HTML解析警告:', parseError.textContent);
        // 不阻止继续，但记录警告
      }
    } catch (parseErr) {
      console.warn('HTML解析错误:', parseErr);
      // 同样不阻止继续
    }

    // 在输出修复后的HTML
    console.log('修复后的HTML结构长度:', cleanCode.length);

    const doc = previewIframe.value.contentDocument;

    try {
      doc.open();
      doc.write(cleanCode);
      doc.close();
    } catch (writeErr) {
      console.error('文档写入错误:', writeErr);
      console.error('尝试写入的HTML:', cleanCode);
      previewError.value = '预览更新失败: 文档写入错误';
      isPreviewLoading.value = false;
      return;
    }

    // 添加Font Awesome支持和错误处理
    try {
      // 添加Font Awesome 5的支持
      const faLink = doc.createElement('link');
      faLink.rel = 'stylesheet';
      faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
      doc.head.appendChild(faLink);

      // 添加错误处理脚本
      const errorHandlingScript = doc.createElement('script');
      errorHandlingScript.textContent = `
        // 处理资源加载失败
        document.addEventListener('error', function(e) {
          console.warn('资源加载失败:', e.target.src || e.target.href);
        }, true);

        // 通知父窗口预览已加载
        window.addEventListener('load', function() {
          window.parent.postMessage({ type: 'preview-loaded' }, '*');
        });
      `;
      doc.head.appendChild(errorHandlingScript);
    } catch (e) {
      console.warn('添加额外资源出错:', e);
    }

    setTimeout(() => {
      isPreviewLoading.value = false;
    }, 1000);

    console.log('实时预览已更新');
  } catch (err) {
    console.error('预览更新失败:', err);
    isPreviewLoading.value = false;
    previewError.value = '预览更新失败: ' + (err instanceof Error ? err.message : '未知错误');
  }
};

// 监听预览模式变化
watch(previewMode, () => {
  if (previewMode.value === 'rendered') {
    nextTick(() => {
      // 优先使用最新可用的代码
      const codeToUse = generatedCode.value || areasIntegratedCode.value || skeletonCode.value;
      if (codeToUse) {
        if (codeType.value === 'html') {
          renderCodeInIframe(codeToUse);
        } else {
          updateVuePreview(codeToUse);
        }
      }
      console.log('切换到渲染预览模式，已更新预览');
    });
  }
});

// 监听代码类型变化
watch(codeType, (newCodeType) => {
  if (previewMode.value === 'rendered') {
    // 优先使用最新可用的代码
    const codeToUse = generatedCode.value || areasIntegratedCode.value || skeletonCode.value;
    if (codeToUse) {
      if (newCodeType === 'html') {
        // 切换到HTML预览
        showVuePreview.value = false;
        nextTick(() => {
          renderCodeInIframe(codeToUse);
        });
      } else {
        // 切换到Vue预览
        updateVuePreview(codeToUse);
      }
    }
  }
});

// 监听各种代码变化，自动更新预览
watch([generatedCode, areasIntegratedCode, skeletonCode],
  ([newGeneratedCode, newAreasCode, newSkeletonCode]) => {
    // 只在渲染预览模式下自动更新
    if (previewMode.value !== 'rendered') return;

    // 选择最优先的有内容的代码
    let codeToUse = '';
    if (newGeneratedCode) codeToUse = newGeneratedCode;
    else if (newAreasCode) codeToUse = newAreasCode;
    else if (newSkeletonCode) codeToUse = newSkeletonCode;

    // 只有当代码变化时才更新预览
    if (codeToUse && codeToUse !== currentPreviewCode.value) {
      console.log('检测到代码变化，自动更新预览');
      currentPreviewCode.value = codeToUse;

      // 根据当前代码类型更新对应的预览
      if (codeType.value === 'html') {
        updatePreview(codeToUse);
      } else {
        updateVuePreview(codeToUse);
      }
    }
  },
  { deep: true } // 深度监听，确保能检测到内容变化
);

// 组件挂载后初始化
onMounted(() => {

  // 初始化预览iframe
  if (previewIframe.value) {
    const initialHtml = `
      <html>
      <head>
        <title>前端代码生成器</title>
        <style>
          body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            background-color: #f8f9fa;
            color: #333;
          }
          h1 {
            margin-bottom: 20px;
            color: #1890ff;
          }
          p {
            text-align: center;
            max-width: 80%;
            line-height: 1.6;
          }
        </style>
      </head>
      <body>
        <h1>前端代码生成器</h1>
        <p>请输入您的需求描述，然后点击"生成代码"按钮开始生成前端页面。</p>
        <p>生成的代码将在此处预览。</p>
      </body>
      </html>
    `;
    updatePreview(initialHtml);

    // 预加载本地备用资源
    preloadLocalFallbacks();

    // 监听iframe消息
    window.addEventListener('message', (event) => {
      if (event.data && event.data.type === 'preview-loaded') {
        console.log('预览加载完成');
        isPreviewLoading.value = false;
      } else if (event.data && event.data.type === 'preview-error') {
        console.error('预览错误:', event.data.error);
        previewError.value = event.data.error || '预览加载失败';
        isPreviewLoading.value = false;
      }
    });
  }
});

// 预加载本地备用资源
const preloadLocalFallbacks = () => {
  if (!previewIframe.value || !previewIframe.value.contentDocument) return;

  const doc = previewIframe.value.contentDocument;
  const head = doc.head;

  // 添加内联的基础Bootstrap样式
  const basicCss = doc.createElement('style');
  basicCss.id = 'local-bootstrap-fallback';
  basicCss.textContent = `
    /* 最小化的Bootstrap核心样式 */
    :root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529}*,::after,::before{box-sizing:border-box}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}h2{font-size:calc(1.325rem + .9vw)}h3{font-size:calc(1.3rem + .6vw)}h4{font-size:calc(1.275rem + .3vw)}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}img{vertical-align:middle}button{border-radius:0;margin:0;font-family:inherit;font-size:inherit;line-height:inherit;text-transform:none}button:focus:not(:focus-visible){outline:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}.container,.container-fluid{width:100%;padding-right:var(--bs-gutter-x,.75rem);padding-left:var(--bs-gutter-x,.75rem);margin-right:auto;margin-left:auto}.container{max-width:1320px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(var(--bs-gutter-y) * -1);margin-right:calc(var(--bs-gutter-x) * -.5);margin-left:calc(var(--bs-gutter-x) * -.5)}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9{flex:0 0 auto;width:100%}.col-12{flex:0 0 auto;width:100%}@media (min-width:576px){.col-sm-6{flex:0 0 auto;width:50%}}@media (min-width:768px){.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-6{flex:0 0 auto;width:50%}.col-md-8{flex:0 0 auto;width:66.66666667%}}@media (min-width:992px){.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-8{flex:0 0 auto;width:66.66666667%}}@media (min-width:1200px){.col-xl-3{flex:0 0 auto;width:25%}}.btn{display:inline-block;font-weight:400;line-height:1.5;color:#212529;text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.btn-primary:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card-body{flex:1 1 auto;padding:1rem 1rem}.card-title{margin-bottom:.5rem}.card-text:last-child{margin-bottom:0}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding-top:.5rem;padding-bottom:.5rem}.navbar-brand{padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;text-decoration:none;white-space:nowrap}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.bg-dark{background-color:#212529!important}.bg-light{background-color:#f8f9fa!important}.bg-primary{background-color:#0d6efd!important}.d-flex{display:flex!important}.d-none{display:none!important}.justify-content-center{justify-content:center!important}.align-items-center{align-items:center!important}.m-0{margin:0!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.p-0{padding:0!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.text-center{text-align:center!important}.text-white{color:#fff!important}@media (min-width:992px){.d-lg-block{display:block!important}.d-lg-none{display:none!important}}
  `;
  head.appendChild(basicCss);

  // 添加内联的基础Font Awesome图标
  const faIcons = doc.createElement('style');
  faIcons.id = 'local-fontawesome-fallback';
  faIcons.textContent = `
    /* 最小化的Font Awesome核心图标 */
    .fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-search:before{content:"\\f002"}.fa-user:before{content:"\\f007"}.fa-home:before{content:"\\f015"}.fa-clock-o:before{content:"\\f017"}.fa-list:before{content:"\\f03a"}.fa-check:before{content:"\\f00c"}.fa-close:before{content:"\\f00d"}.fa-remove:before{content:"\\f00d"}.fa-times:before{content:"\\f00d"}.fa-cog:before{content:"\\f013"}.fa-gear:before{content:"\\f013"}.fa-trash-o:before{content:"\\f014"}.fa-file-o:before{content:"\\f016"}.fa-download:before{content:"\\f019"}.fa-arrow-circle-o-down:before{content:"\\f01a"}.fa-arrow-circle-o-up:before{content:"\\f01b"}.fa-play-circle-o:before{content:"\\f01d"}.fa-repeat:before{content:"\\f01e"}.fa-rotate-right:before{content:"\\f01e"}.fa-refresh:before{content:"\\f021"}.fa-list-alt:before{content:"\\f022"}.fa-lock:before{content:"\\f023"}.fa-flag:before{content:"\\f024"}.fa-tag:before{content:"\\f02b"}.fa-book:before{content:"\\f02d"}.fa-bookmark:before{content:"\\f02e"}.fa-print:before{content:"\\f02f"}.fa-camera:before{content:"\\f030"}.fa-video-camera:before{content:"\\f03d"}.fa-photo:before{content:"\\f03e"}.fa-image:before{content:"\\f03e"}.fa-picture-o:before{content:"\\f03e"}.fa-pencil:before{content:"\\f040"}.fa-edit:before{content:"\\f044"}.fa-pencil-square-o:before{content:"\\f044"}
  `;
  head.appendChild(faIcons);

  // 添加基础的jQuery和Bootstrap JS模拟
  const basicJs = doc.createElement('script');
  basicJs.id = 'local-js-fallback';
  basicJs.textContent = `
    // 基础jQuery模拟
    if (typeof jQuery === 'undefined') {
      window.jQuery = window.$ = function(selector) {
        const elements = document.querySelectorAll(selector);
        return {
          on: function(event, callback) {
            elements.forEach(el => el.addEventListener(event, callback));
            return this;
          },
          addClass: function(className) {
            elements.forEach(el => el.classList.add(className));
            return this;
          },
          removeClass: function(className) {
            elements.forEach(el => el.classList.remove(className));
            return this;
          },
          toggle: function() {
            elements.forEach(el => {
              if (window.getComputedStyle(el).display === 'none') {
                el.style.display = 'block';
              } else {
                el.style.display = 'none';
              }
            });
            return this;
          },
          html: function(content) {
            if (content === undefined) {
              return elements[0] ? elements[0].innerHTML : '';
            }
            elements.forEach(el => { el.innerHTML = content; });
            return this;
          },
          text: function(content) {
            if (content === undefined) {
              return elements[0] ? elements[0].textContent : '';
            }
            elements.forEach(el => { el.textContent = content; });
            return this;
          }
        };
      };
    }

    // 基础Bootstrap组件模拟
    if (typeof bootstrap === 'undefined') {
      window.bootstrap = {
        Modal: class {
          constructor(element) {
            this.element = typeof element === 'string' ? document.querySelector(element) : element;
          }
          show() {
            if (this.element) this.element.style.display = 'block';
          }
          hide() {
            if (this.element) this.element.style.display = 'none';
          }
          toggle() {
            if (this.element) {
              if (window.getComputedStyle(this.element).display === 'none') {
                this.element.style.display = 'block';
              } else {
                this.element.style.display = 'none';
              }
            }
          }
          static getInstance(element) {
            return new this(element);
          }
        },
        Tooltip: class {
          constructor(element) {
            this.element = typeof element === 'string' ? document.querySelector(element) : element;
          }
          show() {}
          hide() {}
          toggle() {}
          static getInstance(element) {
            return new this(element);
          }
        }
      };
    }

    // 控制台信息
    console.log('本地备用资源已加载，将在CDN资源失败时使用');
  `;
  head.appendChild(basicJs);
};

// Vue组件预览更新
const updateVuePreview = (code: string) => {
  try {
    isPreviewLoading.value = true;
    previewError.value = '';

    // 验证和清理代码
    if (!code || code.trim() === '') {
      previewError.value = '预览代码为空';
      isPreviewLoading.value = false;
      return;
    }

    // 清理代码中的markdown标记
    let cleanCode = code.replace(/```vue|```/g, '').trim();

    // 更新RemoteComponent的内容
    if (remoteComponent.value) {
      // 更新sfcContent
      sfcContent.value = cleanCode;

      // 如果Vue组件已经显示，刷新它
      if (showVuePreview.value) {
        nextTick(() => {
          if (remoteComponent.value) {
            remoteComponent.value.transform?.();
          }
        });
      } else {
        // 如果还没显示，设置为显示
        showVuePreview.value = true;
      }
    }

    setTimeout(() => {
      isPreviewLoading.value = false;
    }, 1000);

    console.log('Vue组件预览已更新');
  } catch (err) {
    console.error('Vue预览更新失败:', err);
    isPreviewLoading.value = false;
    previewError.value = 'Vue预览更新失败: ' + (err instanceof Error ? err.message : '未知错误');
  }
};

// 存储Vue SFC内容
const sfcContent = ref('');
</script>

<style scoped>
/* 全局样式 */
.app-container {
  display: flex;
  height: 100vh;
  overflow: hidden;
  background-color: #f0f2f5;
  padding: 16px;
  gap: 16px;
}

/* 左侧输入区域 */
.input-area {
  width: 35%;
  display: flex;
  flex-direction: column;
  height:  calc(100% - 90px);
  overflow: hidden;
  gap: 16px;
}

/* 右侧结果区域 */
.result-area {
  width: 65%;
  display: flex;
  flex-direction: column;
  height: calc(100% - 90px);
  overflow: hidden;
  background-color: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
  transition: all 0.3s;
}

/* 标题头部 */
.header {
  padding: 16px;
  background-color: #ffffff;
  border-radius: 12px 12px 0 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}

.header h2 {
  margin: 0;
  font-size: 1.5rem;
  color: #1890ff;
}

/* 左上部分区域 */
.left-top {
  display: flex;
  flex-direction: column;
  gap: 16px;
  background-color: #ffffff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
  padding-bottom: 16px;
  transition: all 0.3s;
  max-height: 40%;
  overflow: auto;
}

/* 需求输入区域 */
.requirement-input {
  padding: 0 16px 16px;
  display: flex;
  flex-direction: column;
}

.input-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.input-header span {
  font-weight: 500;
  color: #333;
}

.button-group {
  display: flex;
  gap: 8px;
}

.requirement-textarea {
  width: 100%;
  height: 150px;
  padding: 12px;
  border: 1px solid #e8e8e8;
  border-radius: 8px;
  resize: none;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  outline: none;
  transition: all 0.3s;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.02);
}

.requirement-textarea:focus {
  border-color: #40a9ff;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
}

/* 生成设置区域 */
.generation-settings {
  padding: 0 16px 16px;
  background-color: #f9f9f9;
  border-radius: 8px;
  margin: 0 16px;
}

.settings-header {
  font-weight: 500;
  margin-bottom: 16px;
  color: #333;
  padding-top: 16px;
  border-bottom: 1px solid #eee;
  padding-bottom: 8px;
}

/* 设置项 */
.setting-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding: 8px 12px;
  background-color: white;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
  transition: all 0.2s;
}

.setting-item:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
  transform: translateY(-1px);
}

/* 文本域风格设置项 */
.setting-item-textarea {
  display: flex;
  flex-direction: column;
  margin-bottom: 16px;
  padding: 8px 12px;
  background-color: white;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
  transition: all 0.2s;
}

.setting-item-textarea:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
  transform: translateY(-1px);
}

.setting-item-textarea .setting-label {
  margin-bottom: 8px;
}

.setting-label {
  display: flex;
  align-items: center;
  gap: 8px;
}

.color-pickers {
  display: flex;
  gap: 8px;
}

/* 生成进度区域 */
.generation-progress {
  padding: 0 16px;
}

.progress-header {
  font-weight: 500;
  margin-bottom: 12px;
  color: #333;
}

/* 聊天内容区域 */
.chat-content {
  flex: 1;
  overflow-y: auto;
  background-color: #ffffff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 50%;
}

/* 消息卡片 */
.message {
  background-color: #f9f9f9;
  border-radius: 10px;
  padding: 16px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
  transition: transform 0.2s, box-shadow 0.2s;
  border-left: 4px solid #1890ff;
}

.message:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.06);
}

.message-title {
  font-weight: 600;
  margin-bottom: 12px;
  color: #333;
  border-bottom: 1px solid #eee;
  padding-bottom: 8px;
}

.message-content {
  white-space: pre-wrap;
  overflow-x: auto;
  padding: 12px;
  background-color: white;
  border-radius: 6px;
  border: 1px solid #f0f0f0;
  font-size: 14px;
}

.message-content.code {
  font-family: 'Courier New', Courier, monospace;
  font-size: 13px;
  background-color: #fafafa;
}

/* 预览切换按钮 */
.preview-toggle {
  display: flex;
  border-bottom: 1px solid #f0f0f0;
  background-color: #fff;
  border-radius: 12px 12px 0 0;
}

.preview-toggle button {
  flex: 1;
  padding: 14px;
  background: none;
  border: none;
  cursor: pointer;
  font-weight: 500;
  color: #666;
  transition: all 0.3s;
  position: relative;
}

.preview-toggle button.active {
  color: #1890ff;
}

.preview-toggle button.active::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 20%;
  width: 60%;
  height: 3px;
  background-color: #1890ff;
  border-radius: 3px 3px 0 0;
}

.preview-toggle button:hover:not(.active) {
  color: #40a9ff;
  background-color: #f5f5f5;
}

/* 代码预览 */
.code-preview {
  flex: 1;
  padding: 20px;
  overflow: auto;
  background-color: #fafafa;
  border-radius: 0 0 12px 12px;
}

.code-preview pre {
  margin: 0;
  white-space: pre-wrap;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.6;
}

/* 渲染预览 */
.rendered-preview {
  flex: 1;
  position: relative;
  overflow: hidden;
  border-radius: 0 0 12px 12px;
}

.preview-iframe {
  width: 100%;
  height: 100%;
  border: none;
  background-color: white;
}

.preview-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  background-color: #fafafa;
  color: #999;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #1890ff;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.preview-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  background-color: #fafafa;
  color: #999;
}

.preview-error i {
  margin-bottom: 8px;
}

.preview-error p {
  margin: 8px 0;
}

.empty-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  background-color: #fafafa;
  color: #999;
}

.empty-preview p {
  margin: 8px 0;
}

.retry-btn {
  background-color: #1890ff;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 2px 6px rgba(24, 144, 255, 0.2);
}

.retry-btn:hover {
  background-color: #40a9ff;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}

/* 区域标签 */
.areas-list,
.areas-progress {
  padding: 16px;
  margin-top: 12px;
  background-color: #f9f9f9;
  border-radius: 10px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
}

.areas-title {
  font-weight: 600;
  margin-bottom: 12px;
  color: #333;
}

.area-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.area-tag {
  padding: 6px 12px;
  background-color: #f5f5f5;
  border-radius: 20px;
  border: 1px solid #eee;
  position: relative;
  transition: all 0.3s;
  font-size: 13px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
}

.area-tag:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
}

.area-tag.completed {
  background-color: #e6f7ff;
  border-color: #91d5ff;
  color: #1890ff;
  box-shadow: 0 2px 4px rgba(24, 144, 255, 0.1);
}

.area-tag.current {
  background-color: #fff7e6;
  border-color: #ffd591;
  color: #fa8c16;
  font-weight: bold;
  box-shadow: 0 2px 8px rgba(250, 140, 22, 0.15);
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(250, 140, 22, 0.4);
  }
  70% {
    box-shadow: 0 0 0 5px rgba(250, 140, 22, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(250, 140, 22, 0);
  }
}

/* 按钮样式 */
.generate-btn {
  background-color: #1890ff;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 2px 6px rgba(24, 144, 255, 0.2);
}

.generate-btn:hover:not(:disabled) {
  background-color: #40a9ff;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}

.generate-btn:disabled {
  background-color: #bfbfbf;
  cursor: not-allowed;
  box-shadow: none;
}

.cancel-btn {
  background-color: #ff4d4f;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 2px 6px rgba(255, 77, 79, 0.2);
}

.cancel-btn:hover {
  background-color: #ff7875;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3);
}

/* 进度列表 */
.unified-progress-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  background-color: #f9f9f9;
  border-radius: 10px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
  max-height: 300px;
  overflow-y: auto;
}

.progress-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background-color: white;
  border-radius: 6px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
  transition: all 0.2s;
  position: relative;
}

.progress-item:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 14px;
  bottom: -8px;
  width: 2px;
  height: 8px;
  background-color: #e8e8e8;
  z-index: 1;
}

.progress-item:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
  transform: translateY(-1px);
}

.progress-icon {
  font-size: 16px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.progress-label {
  font-weight: 500;
  color: #333;
  flex: 1;
}

.progress-item.completed {
  background-color: #f6ffed;
  border-left: 3px solid #52c41a;
}

.progress-item.completed .progress-icon {
  color: white;
  background-color: #52c41a;
}

.progress-item.current {
  background-color: #fff7e6;
  border-left: 3px solid #fa8c16;
}

.progress-item.current .progress-icon {
  color: white;
  background-color: #fa8c16;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(250, 140, 22, 0.4);
  }
  70% {
    box-shadow: 0 0 0 5px rgba(250, 140, 22, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(250, 140, 22, 0);
  }
}

/* Vue预览容器样式 */
.vue-preview-container {
  width: 100%;
  height: 100%;
  background-color: #ffffff;
  overflow: hidden;
  border-radius: 0 0 12px 12px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  position: relative;
}
</style>
